package xyz.xtt.exchange.support;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import xyz.xtt.exchange.constants.ErrorMessage;
import xyz.xtt.exchange.exception.ChainException;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 国美靓号api接口
 *
 * @author dale
 * @since 2024/12/31
 **/
@Component
@RefreshScope
@Slf4j
public class GomeLuckPhoneHttpService {
    @Value("${gome.luck.phone.channel.account}")
    private String channelAccount;
    @Value("${gome.luck.phone.channel.secret}")
    private String channelSecret;
    @Value("${gome.luck.phone.url}")
    private String fetchUrl;


    /**
     * 预占号码
     * @param luckPhone
     * @return
     */
    public boolean preLockPhone(String luckPhone) {
        // 构造请求参数
        String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        Map<String, String> parameters = Map.of(
                "channelAccount", channelAccount,
                "timeStamp", timeStamp,
                "sign", generateSign(timeStamp),
                "telephone", luckPhone
        );

        String formData = buildFormData(parameters);

        // 创建 HttpClient
        HttpClient client = HttpClient.newHttpClient();

        // 构造 POST 请求
        String url = fetchUrl + "/lockPhone";
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .header("Accept", "application/json; charset=utf-8")
                .POST(HttpRequest.BodyPublishers.ofString(formData))
                .build();
        log.info("preLockPhone Sending request to url:{} with params:{}", url, formData);

        // 发送请求并获取响应
        int maxTries = 4;
        while (maxTries-- > 0) {
            try {
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                String body = decodeUnicode(response.body());
                JSONObject bodyObj = JSONUtil.parseObj(body);
                if (response.statusCode() == 200) {
                    String state = bodyObj.getStr("state");
                    if (Objects.equals(state, "0000")){
                        return true;
                    }else {
                        //不可恢复异常打印日志后直接返回
                        log.warn("preLockPhone error res:{}", body);
                        if (Objects.equals(state, "2002")){
                            throw new ChainException(ErrorMessage.LUCK_PHONE_LOCK_FAIL);
                        } else if (Objects.equals(state, "3001")) {
                            throw new ChainException(ErrorMessage.LUCK_PHONE_CAN_NOT_USE);
                        } else {
                            throw new ChainException(ErrorMessage.ERROR_GENERAL);
                        }
                    }
                } else {
                    //可恢复异常打印日志后重试
                    log.error("preLockPhone error statusCode:{} body:{}", body);
                    try {
                        Thread.sleep(100L);
                    }catch (InterruptedException e){
                        Thread.currentThread().interrupt();
                    }
                }
            } catch (Exception e) {
                if (e instanceof ChainException){
                    throw (ChainException) e;
                }
                log.error("preLockPhone error:{}", e.getMessage());
            }
        }
        throw new ChainException(ErrorMessage.ERROR_GENERAL);
    }

    /**
     * 提交订单
     * @param luckPhone
     * @param receiverPhone
     * @param orderNo
     * @param remark
     * @return
     */
    public boolean submitOrder(String luckPhone, String receiverPhone, long orderNo, String remark) {
        // 构造请求参数
        String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        Map<String, String> parameters = Map.of(
                "channelAccount", channelAccount,
                "timeStamp", timeStamp,
                "sign", generateSign(timeStamp),
                "telephone", luckPhone,
                "orderNo", orderNo + "",
                "receiverPhone", receiverPhone,
                "Remark",StringUtils.isNotBlank(remark) ? remark : ""
        );

        String formData = buildFormData(parameters);

        // 创建 HttpClient
        HttpClient client = HttpClient.newHttpClient();

        // 构造 POST 请求
        String url = fetchUrl + "/postOrder";
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .header("Accept", "application/json; charset=utf-8")
                .POST(HttpRequest.BodyPublishers.ofString(formData))
                .build();

        // 发送请求并获取响应
        int maxTries = 4;
        while (maxTries-- > 0) {
            try {
                log.info("submitOrder Sending request to url:{} with params:{}", url, formData);
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                String body = decodeUnicode(response.body());
                JSONObject bodyObj = JSONUtil.parseObj(body);
                if (response.statusCode() == 200) {
                    String state = bodyObj.getStr("state");
                    if (Objects.equals(state, "0000")){
                        return true;
                    }else {
                        log.warn("submitOrder error res:{}", body);
                        if (Objects.equals(state, "2000") || Objects.equals(state, "2001") || Objects.equals(state, "3001")){
                            throw new ChainException(ErrorMessage.LUCK_PHONE_CAN_NOT_USE);
                        }
                    }
                } else {
                    log.error("submitOrder error statusCode:{} body:{}", body);
                }
            } catch (Exception e) {
                if (e instanceof ChainException){
                    throw (ChainException) e;
                }
                log.error("submitOrder error:{}", e.getMessage());
            }
        }
        throw new ChainException(ErrorMessage.ERROR_GENERAL);
    }

    /**
     * 获取订单状态
     * @param orderNo 业务方订单号
     * @return 订单状态
     */
    public Integer fetchOrderStatus(Long orderNo) {
        // 构造请求参数
        String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        Map<String, String> parameters = Map.of(
                "channelAccount", channelAccount,
                "timeStamp", timeStamp,
                "sign", generateSign(timeStamp),
                "orderNo", orderNo + ""
        );

        String formData = buildFormData(parameters);

        // 创建 HttpClient
        HttpClient client = HttpClient.newHttpClient();

        // 构造 POST 请求
        String url = fetchUrl + "/queryOrder";
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .header("Accept", "application/json; charset=utf-8")
                .POST(HttpRequest.BodyPublishers.ofString(formData))
                .build();

        // 发送请求并获取响应
        int maxTries = 4;
        while (maxTries-- > 0) {
            try {
                log.info("fetchOrderStatus Sending request to url:{} with params:{}", url, formData);
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                String body = decodeUnicode(response.body());
                JSONObject bodyObj = JSONUtil.parseObj(body);
                if (response.statusCode() == 200 && Objects.equals(bodyObj.getStr("state"),"0000")) {
                    return Integer.valueOf(bodyObj.getJSONObject("data").getStr("status"));
                } else {
                    log.error("fetchOrderStatus error statusCode:{} body:{}",response.statusCode(), body);
                }
            } catch (Exception e) {
                log.error("fetchOrderStatus error:{}", e.getMessage());
            }
        }
        return null;
    }

    /**
     * 生成签名
     *
     * @param timeStamp
     * @return
     */
    private String generateSign(String timeStamp) {
        return SecureUtil.md5(channelAccount + channelSecret + timeStamp).toLowerCase();
    }

    /**
     * 将参数 Map 转换为 application/x-www-form-urlencoded 格式
     *
     * @param data
     * @return
     */
    private static String buildFormData(Map<String, String> data) {
        return data.entrySet().stream()
                .map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "="
                        + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8))
                .collect(Collectors.joining("&"));
    }

    /**
     * 解码 Unicode 编码的字符串
     *
     * @param encoded
     * @return
     */
    private static String decodeUnicode(String encoded) {
        StringBuilder decoded = new StringBuilder();
        int i = 0;
        while (i < encoded.length()) {
            char c = encoded.charAt(i++);
            if (c == '\\' && i < encoded.length() && encoded.charAt(i) == 'u') {
                int codePoint = Integer.parseInt(encoded.substring(i + 1, i + 5), 16);
                decoded.append((char) codePoint);
                i += 5;
            } else {
                decoded.append(c);
            }
        }
        return decoded.toString();
    }



}
